package com.xxxx.server.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.security.access.AccessDeniedException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * POI - xsl导出公共类
 *
 * @author : honors
 */
@Slf4j
public class PoiXslUtils {
    /**
     * xsl工作簿
     */
    private XSSFWorkbook wb;
    /**
     * 页
     */
    private XSSFSheet sheet;
    /**
     * 行
     */
    private XSSFRow row;
    /**
     * 行位置 - 初始化为0
     */
    private int rowIndex;
    /**
     * 列样式
     */
    private XSSFCellStyle styleCell;

    /**
     * 初始化一个xsl工作簿
     */
    public PoiXslUtils() {
        wb = new XSSFWorkbook();
    }

    /**
     * 创建一页
     */
    public void createSheet() {
        rowIndex = 0;
        sheet = wb.createSheet();
        sheet.createRow(rowIndex);
        row = sheet.createRow(rowIndex);
    }

    /**
     * 创建单元格 风格
     *
     * @return XSSFCellStyle
     */
    public XSSFCellStyle createStyle() {
        return wb.createCellStyle();
    }

    /**
     * 创建一行
     */
    public void createRow() {
        row = sheet.createRow(++rowIndex);
    }

    /**
     * 行数据写入
     *
     * @param rowDataList 数据集合
     * @param style       风格
     */
    public void writeRow(List<String> rowDataList, XSSFCellStyle style) {
        int cellIndex = 0;
        for (String data : rowDataList) {
            XSSFCell cell = row.createCell(cellIndex++);
            cell.setCellValue(data);
            cell.setCellStyle(style);
        }
    }

    /**
     * 行数据写入
     *
     * @param rowDataList 数据集合
     */
    public void writeRow(List<String> rowDataList) {
        int cellIndex = 0;
        for (String data : rowDataList) {
            XSSFCell cell = row.createCell(cellIndex++);
            cell.setCellValue(data);
        }
    }

    public void writeRow(List<String> rowDataList, String prefix) {
        int cellIndex = 0;
        for (String data : rowDataList) {
            XSSFCell cell = row.createCell(cellIndex++);
            if (data.startsWith(prefix)) {
                cell.setCellValue(data);
                XSSFCellStyle cellStyle = wb.createCellStyle();
                XSSFFont font = wb.createFont();
                font.setBold(true);
                cellStyle.setFont(font);
                cell.setCellStyle(cellStyle);
                continue;
            }
            cell.setCellValue(data);
        }
    }

    /**
     * 写出文件
     *
     * @param output 流
     * @throws IOException 异常处理
     */
    public void write(OutputStream output) throws IOException {
        wb.write(output);
    }

    /**
     * 单一格子操作
     *
     * @param value     内容
     * @param style     格式
     * @param cellIndex 位置
     */
    public void writeCell(String value, XSSFCellStyle style, Integer cellIndex) {
        XSSFCell cell = row.createCell(cellIndex);
        cell.setCellValue(value);
        cell.setCellStyle(style);
    }

    /**
     * 合并单元格
     *
     * @param region 合并规则
     */
    public void mergeCell(CellRangeAddress region) {
        sheet.addMergedRegion(region);
    }

    /*=================分割-上面为导出操作-下面为导入解析=================*/

    /**
     * 解析excel - 后续待继续改进
     *
     * @param path 文件路径
     * @return 解析内容
     */
    public static List<List<String>> readExcel(String path) {
        String fileType = path.substring(path.lastIndexOf(".") + 1);
        List<List<String>> rowList = new ArrayList<>();
        //读取excel文件
        try (InputStream inputStream = new FileInputStream(path)) {
            String xls = "xls";
            //获取工作薄
            Workbook wb;
            if (fileType.equals(xls)) {
                wb = new HSSFWorkbook(inputStream);
            } else {
                wb = new XSSFWorkbook(inputStream);
            }
            //读取第一个工作页sheet
            Sheet sheet = wb.getSheetAt(0);
            //第一行为标题
            int size = 0;
            for (Row row : sheet) {
                if (size == 0) {
                    size = row.getLastCellNum();
                }
                ArrayList<String> list = new ArrayList<>();
                for (int i = 0; i < size; i++) {
                    Cell cell = row.getCell(i);
                    if (cell == null) {
                        list.add("");
                        continue;
                    } else {
                        if (size > 0 && i >= 9 && i <= 12) {
                            // 日期处理，例子poi会把'2020-08-01'读取为'01-八月-2020'，所以要进行汉字转阿拉伯数字处理,
                            String value = "";
                            if (row.getRowNum() == 0) {
                                //表头
                                value = cell.toString();
                            } else {
                                DataFormatter df = new DataFormatter();
                                value = df.formatCellValue(cell);
                            }
                            list.add(value);
                        } else {
                            if (cell.getCellType() == 0) {
                                list.add(String.valueOf(cell.getNumericCellValue()));
                            } else {
                                list.add(cell.getStringCellValue());
                            }
                        }
                    }
                }
                rowList.add(list);
            }
        } catch (IOException e) {
            throw new AccessDeniedException("excel导入、系统异常");
        }
        return rowList;
    }

    /**
     * 获取新的文件名
     *
     * @param module 模块
     * @return 文件名
     */
    public String getNewName(String module) {
        return module + new SimpleDateFormat("yyyyMMddHHMMSS").format(new Date()) + ".xlsx";
    }

    /**
     * 导出temp路径
     *
     * @return String
     */
    public String getTempPath() {
        return File.separator + "resource" + File.separator + "temp" + File.separator;
    }

    /**
     * 新增 - 模板
     *
     * @param fileName   模板文件名
     * @param headerData 头部字段
     * @param tempDir    保存的文件夹
     * @throws Exception 异常
     */
    public static String writerTemplate(String fileName, List<String> headerData, String tempDir) {
        PoiXslUtils poiXslUtil = new PoiXslUtils();
        poiXslUtil.createSheet();
        for (int i = 0; i < headerData.size(); i++) {
            String data = headerData.get(i);
            if (data == null)
                continue;
        }
        //写入
        poiXslUtil.writeRow(headerData, "*");
        try (OutputStream output = new FileOutputStream(tempDir + fileName)) {
            poiXslUtil.write(output);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("writerTemplate fail: ", e);
        }
        return tempDir + fileName;
    }

    /**
     * 检查是否excel文件
     *
     * @param path 文件路径
     */
    public static boolean checkIsExcel(String path) {
        String fileType = path.substring(path.lastIndexOf(".") + 1);
        String xls = "xls";
        String xlsX = "xlsx";
        return !xls.equals(fileType) && !xlsX.equals(fileType);
    }

    /**
     * 实现功能描述：写内容
     *
     * @param url 文件路径
     * @return
     */
    public void writeContent(String url) throws IOException {
        try (OutputStream output = new FileOutputStream(url);) {
            write(output);
            output.flush();
        }
    }

    /**
     * 行数据写入，需要创建列样式
     *
     * @param rowDataList 数据集合
     */
    public void writeRowData(List<String> rowDataList) {
        int cellIndex = 0;
        for (String data : rowDataList) {
            XSSFCell cell = row.createCell(cellIndex++);
            cell.setCellValue(data);
            cell.setCellStyle(styleCell);
        }
    }

    /**
     * 实现功能描述：创建列样式
     */
    public void createXSSFCellStyle() {
        styleCell = wb.createCellStyle();
        // 文本格式
        XSSFDataFormat dataFormat = wb.createDataFormat();
        styleCell.setDataFormat(dataFormat.getFormat("@"));
    }
}
